package com.xjt.excel.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xjt.excel.entity.PubImpExcelJdLog;
import com.xjt.excel.entity.PubImpExcelModel;
import com.xjt.excel.entity.PubImpExcelModelcol;
import com.xjt.excel.mapper.PubImpExcelJdLogMapper;
import com.xjt.excel.service.IImpExcelService;
import com.xjt.excel.service.IPubImpExcelJdLogService;
import com.xjt.excel.service.IPubImpExcelModelService;
import com.xjt.excel.util.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.UncategorizedSQLException;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileNotFoundException;
import java.time.LocalDateTime;
import java.util.*;

/**
 * <p>
 * 批量导入日志信息表（提供导入日志查询功能） 服务实现类
 * </p>
 *
 * @author xujiangtao
 * @since 2021-05-18
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class PubImpExcelJdLogServiceImpl extends ServiceImpl<PubImpExcelJdLogMapper, PubImpExcelJdLog> implements IPubImpExcelJdLogService {

	public final IPubImpExcelModelService pubImpExcelModelService;
	public final PubImpExcelModelcolServiceImpl pubImpExcelModelcolService;
	public final PubImpExcelValidLogServiceImpl pubImpExcelValidLogService;
	public final PubImpExcelValidRuleServiceImpl pubImpExcelValidRuleService;

	/**
	 * 接收文件保存位置
	 */
	@Value("${filepath}")
	public String importExcelFile;

	@Override
	public Map<String,Object> importExcel(MultipartFile file, Long menuId)
	{
		Map<String, Object> message = new HashMap<>();
		if (file.isEmpty()){
			message.put("code", 400);
			message.put("msg", "文件为空");
			return message;
		}
		long startData = System.currentTimeMillis();
		// 判断文件是否为空
		LocalDateTime startTime = LocalDateTime.now();
		String path = importExcelFile;
		ReadExcelUtil.setPubImpExcelValidLogServiceImpl(pubImpExcelValidLogService);
		ReadExcelUtil.setPubImpExcelValidRuleServiceImpl(pubImpExcelValidRuleService);
		String originalFilename = file.getOriginalFilename();
		String fileMd5String;
		try {
			fileMd5String = MD5File.getFileMD5String(FileUtil.multipartFileToFile(file));
			QueryWrapper<PubImpExcelJdLog> qw = new QueryWrapper<>();
			qw.eq("state", 1);
			qw.eq("jd_state", "从临时表插入数据到正式表完成");
			qw.eq("md5code", fileMd5String);
			PubImpExcelJdLog one = this.getOne(qw);
			if (one!=null){
				message.put("code", 408);
				message.put("msg", "当前表已存在");
				return message;
			}
		} catch (Exception e) {
			e.printStackTrace();
			message.put("code", 416);
			message.put("msg", "表数据异常");
			return message;
		}
		//判断是不是excel文件
		if (!ReadExcelUtil.validateExcel(originalFilename)){
			message.put("code", 403);
			message.put("msg", "不是excel文件");
			return message;
		}
		String[] split = originalFilename.split("\\.");
		//获取上传文件的后缀
		String suffix = split[split.length-1];
		try {
			// 文件保存路径
			String filePath = path + "/" + UUID.randomUUID().toString().replace("-", "")+"."+suffix;
			QueryWrapper<PubImpExcelModel> qmodel = new QueryWrapper<>();
			qmodel.eq("menu_id", menuId);
			qmodel.eq("state", 1);
			//模板表信息
			List<PubImpExcelModel> excelModels = pubImpExcelModelService.list(qmodel);
			if (excelModels == null || excelModels.size()<1) {
				message.put("code", 501);
				message.put("msg", "未配置导出模板");
				return message;
			}
			for (int i = 0; i < excelModels.size(); i++) {
				QueryWrapper<PubImpExcelModelcol> modelcol = new QueryWrapper<>();
				modelcol.eq("state", 1);
				modelcol.eq("model_id", excelModels.get(i).getId());
				//字段列信息
				List<PubImpExcelModelcol> modelcolList = pubImpExcelModelcolService.list(modelcol);
				//表头信息
				Map<Integer, String> res = ReadExcelUtil.readExcelhead(file,0);
				PubImpExcelJdLog pubImpExcelJdLog = new PubImpExcelJdLog();
				pubImpExcelJdLog.setState(1);
				pubImpExcelJdLog.setMenuId(menuId);
				pubImpExcelJdLog.setPcNum(FileUtils.getUUID());
				pubImpExcelJdLog.setJdState("上传中");
				pubImpExcelJdLog.setStartTime(startTime);
				pubImpExcelJdLog.setOperUid(0L);
				pubImpExcelJdLog.setSourceFileName(originalFilename);
				pubImpExcelJdLog.setSouceFilePath(filePath);
				pubImpExcelJdLog.setMd5code(fileMd5String);
				//记录保存日志信息
				this.saveOrUpdate(pubImpExcelJdLog);
				Long pubImpExcelJdLogId = pubImpExcelJdLog.getId();
				//临时表明
				String tableName = "i"+excelModels.get(i).getId()+"_"+pubImpExcelJdLogId;
				pubImpExcelJdLog.setJdState("创建临时表");
				pubImpExcelJdLog.setTmpTableName(tableName);
				this.saveOrUpdate(pubImpExcelJdLog);
				//创建临时表
				pubImpExcelModelService.createTable(tableName, modelcolList);
				//保存目录如果不存在，则递归创建目录
				if (!new File(filePath).exists()){
					if (new File(filePath).mkdirs()){
						log.info("父目录创建成功");
					}
				}
				//将接受的文件保存
				if (i==0){
					file.transferTo(new File(filePath));
				}
				pubImpExcelJdLog.setJdState("上传成功");
				this.saveOrUpdate(pubImpExcelJdLog);

				message.put("filePath", filePath);
				pubImpExcelJdLog.setJdState("开始解析");
				this.saveOrUpdate(pubImpExcelJdLog);
				Map<String, Object> excelInfos;
				try {
					//获取的excel数据
					excelInfos = ReadExcelUtil.getExcelInfo(filePath, modelcolList, pubImpExcelJdLogId,res,i);
				} catch (FileNotFoundException e){
					e.printStackTrace();
					message.put("code", 506);
					message.put("msg", "找不到文件");
					return message;
				}catch (Exception e){
					e.printStackTrace();
					message.put("code", 504);
					message.put("msg", "数据解析异常,excel数据不匹配");
					return message;
				}
				assert excelInfos != null;
				List<List<String>> excelInfo = (List<List<String>>) excelInfos.get("list");
				List<String> excelColumnList = new ArrayList<>();
				List<String> colCodeList = new ArrayList<>();
				for (PubImpExcelModelcol pubImpExcelModelcol : modelcolList) {
					String excelColumn = pubImpExcelModelcol.getExcelColumn();
					String colCode = pubImpExcelModelcol.getColCode();
					excelColumnList.add(excelColumn);
					colCodeList.add(colCode);
				}
				assert excelInfo != null;
				pubImpExcelJdLog.setJdState("开始插入数据到临时表");
				this.saveOrUpdate(pubImpExcelJdLog);
				try {
					pubImpExcelModelService.saveData(tableName, excelInfo);
				}catch (UncategorizedSQLException e){
					e.getSQLException();
					message.put("code", 302);
					message.put("msg", "必填项不能为空");
					return message;
				}
				pubImpExcelJdLog.setJdState("插入数据到临时表完成");
				this.saveOrUpdate(pubImpExcelJdLog);
				String serviceName = excelModels.get(i).getServiceName();
				pubImpExcelJdLog.setJdState("开始从临时表插入数据到正式表");
				this.saveOrUpdate(pubImpExcelJdLog);

				IImpExcelService iImpExcelService = (IImpExcelService) SpringContextUtil.getBean(serviceName);
				Integer count = iImpExcelService.importExcelToDb(tableName, excelColumnList, colCodeList);
				pubImpExcelJdLog.setEndTime(LocalDateTime.now());
				pubImpExcelJdLog.setProblemnum(Integer.valueOf(excelInfos.get("fail").toString()));
				pubImpExcelJdLog.setJdState("从临时表插入数据到正式表完成");
				pubImpExcelJdLog.setTotalRow(count);
				//保存日志
				this.saveOrUpdate(pubImpExcelJdLog);
				long endData = System.currentTimeMillis();
				long expendTime = (endData - startData) / 1000;
				message.put("expendTime",expendTime/60+"m"+expendTime%60+"s");
				message.put("temTableName",tableName);
				message.put("status", "success");
				message.put("code", 200);
				message.put("successImportCount", count);
			}
		} catch (Exception e) {
			e.printStackTrace();
			message.put("status", "error");
		}
		return message;
	}
}
